/**
 * GameObjectPools - 游戏对象池配置和管理
 * 为常见的游戏实体提供预配置的对象池
 * @class
 */

import { ObjectPool, ObjectPoolManager, globalPoolManager } from './ObjectPool'
import { Entity, EntityType } from './Entity'

/**
 * 可池化的粒子效果类
 */
export class PoolableParticle extends Entity {
  public life: number = 1.0
  public maxLife: number = 1.0
  public color: string = '#ffffff'
  public alpha: number = 1.0

  constructor() {
    super({
      x: 0,
      y: 0,
      width: 4,
      height: 4,
      type: EntityType.COLLECTIBLE
    })
  }

  /**
   * 更新粒子逻辑
   * @param deltaTime - 帧时间差
   */
  update(deltaTime: number): void {
    this.applyPhysics(deltaTime)
    
    // 更新生命周期
    this.life -= deltaTime / 1000
    this.alpha = Math.max(0, this.life / this.maxLife)
    
    // 生命结束时标记为非活跃
    if (this.life <= 0) {
      this.active = false
    }
  }

  /**
   * 渲染粒子
   * @param ctx - 渲染上下文
   */
  render(ctx: CanvasRenderingContext2D): void {
    if (!this.visible || this.alpha <= 0) return

    ctx.save()
    ctx.globalAlpha = this.alpha
    ctx.fillStyle = this.color
    ctx.fillRect(this.x, this.y, this.width, this.height)
    ctx.restore()
  }

  /**
   * 重置粒子状态
   */
  reset(): void {
    super.reset()
    this.life = 1.0
    this.maxLife = 1.0
    this.color = '#ffffff'
    this.alpha = 1.0
  }

  /**
   * 初始化粒子参数
   * @param x - X坐标
   * @param y - Y坐标
   * @param velocityX - X方向速度
   * @param velocityY - Y方向速度
   * @param life - 生命时长（秒）
   * @param color - 颜色
   */
  initialize(
    x: number, 
    y: number, 
    velocityX: number, 
    velocityY: number, 
    life: number = 1.0, 
    color: string = '#ffffff'
  ): void {
    this.x = x
    this.y = y
    this.velocity.x = velocityX
    this.velocity.y = velocityY
    this.life = life
    this.maxLife = life
    this.color = color
    this.alpha = 1.0
    this.active = true
    this.visible = true
  }
}

/**
 * 可池化的收集品类
 */
export class PoolableCollectible extends Entity {
  public value: number = 10
  public collected: boolean = false

  constructor() {
    super({
      x: 0,
      y: 0,
      width: 20,
      height: 20,
      type: EntityType.COLLECTIBLE
    })
  }

  /**
   * 更新收集品逻辑
   * @param deltaTime - 帧时间差
   */
  update(deltaTime: number): void {
    this.applyPhysics(deltaTime)
    
    // 如果被收集，标记为非活跃
    if (this.collected) {
      this.active = false
    }
  }

  /**
   * 收集物品
   */
  collect(): void {
    this.collected = true
    this.visible = false
  }

  /**
   * 重置收集品状态
   */
  reset(): void {
    super.reset()
    this.value = 10
    this.collected = false
  }

  /**
   * 初始化收集品参数
   * @param x - X坐标
   * @param y - Y坐标
   * @param value - 收集品价值
   */
  initialize(x: number, y: number, value: number = 10): void {
    this.x = x
    this.y = y
    this.value = value
    this.collected = false
    this.active = true
    this.visible = true
  }
}

/**
 * 可池化的子弹/投射物类
 */
export class PoolableProjectile extends Entity {
  public damage: number = 1
  public range: number = 500
  public travelDistance: number = 0

  constructor() {
    super({
      x: 0,
      y: 0,
      width: 8,
      height: 4,
      type: EntityType.PROJECTILE
    })
  }

  /**
   * 更新投射物逻辑
   * @param deltaTime - 帧时间差
   */
  update(deltaTime: number): void {
    const deltaSeconds = deltaTime / 1000
    const speed = Math.sqrt(this.velocity.x ** 2 + this.velocity.y ** 2)
    
    this.applyPhysics(deltaTime)
    this.travelDistance += speed * deltaSeconds
    
    // 超出射程时销毁
    if (this.travelDistance >= this.range) {
      this.active = false
    }
  }

  /**
   * 重置投射物状态
   */
  reset(): void {
    super.reset()
    this.damage = 1
    this.range = 500
    this.travelDistance = 0
  }

  /**
   * 初始化投射物参数
   * @param x - X坐标
   * @param y - Y坐标
   * @param velocityX - X方向速度
   * @param velocityY - Y方向速度
   * @param damage - 伤害值
   * @param range - 射程
   */
  initialize(
    x: number, 
    y: number, 
    velocityX: number, 
    velocityY: number, 
    damage: number = 1, 
    range: number = 500
  ): void {
    this.x = x
    this.y = y
    this.velocity.x = velocityX
    this.velocity.y = velocityY
    this.damage = damage
    this.range = range
    this.travelDistance = 0
    this.active = true
    this.visible = true
  }
}

/**
 * 游戏对象池管理器
 * 提供预配置的对象池和便捷的获取方法
 */
export class GameObjectPools {
  private static instance: GameObjectPools | null = null
  private poolManager: ObjectPoolManager

  private constructor() {
    this.poolManager = globalPoolManager
    this.initializePools()
  }

  /**
   * 获取单例实例
   * @returns GameObjectPools实例
   */
  public static getInstance(): GameObjectPools {
    if (!GameObjectPools.instance) {
      GameObjectPools.instance = new GameObjectPools()
    }
    return GameObjectPools.instance
  }

  /**
   * 初始化所有对象池
   */
  private initializePools(): void {
    // 粒子效果池
    const particlePool = new ObjectPool<PoolableParticle>({
      initialSize: 50,
      maxSize: 200,
      createFn: () => new PoolableParticle()
    })
    this.poolManager.registerPool('particles', particlePool)

    // 收集品池
    const collectiblePool = new ObjectPool<PoolableCollectible>({
      initialSize: 20,
      maxSize: 100,
      createFn: () => new PoolableCollectible()
    })
    this.poolManager.registerPool('collectibles', collectiblePool)

    // 投射物池
    const projectilePool = new ObjectPool<PoolableProjectile>({
      initialSize: 30,
      maxSize: 150,
      createFn: () => new PoolableProjectile()
    })
    this.poolManager.registerPool('projectiles', projectilePool)
  }

  /**
   * 获取粒子对象
   * @returns 粒子实例
   */
  getParticle(): PoolableParticle | undefined {
    return this.poolManager.borrow<PoolableParticle>('particles')
  }

  /**
   * 归还粒子对象
   * @param particle - 要归还的粒子
   */
  returnParticle(particle: PoolableParticle): void {
    this.poolManager.return('particles', particle)
  }

  /**
   * 获取收集品对象
   * @returns 收集品实例
   */
  getCollectible(): PoolableCollectible | undefined {
    return this.poolManager.borrow<PoolableCollectible>('collectibles')
  }

  /**
   * 归还收集品对象
   * @param collectible - 要归还的收集品
   */
  returnCollectible(collectible: PoolableCollectible): void {
    this.poolManager.return('collectibles', collectible)
  }

  /**
   * 获取投射物对象
   * @returns 投射物实例
   */
  getProjectile(): PoolableProjectile | undefined {
    return this.poolManager.borrow<PoolableProjectile>('projectiles')
  }

  /**
   * 归还投射物对象
   * @param projectile - 要归还的投射物
   */
  returnProjectile(projectile: PoolableProjectile): void {
    this.poolManager.return('projectiles', projectile)
  }

  /**
   * 创建粒子效果
   * @param x - X坐标
   * @param y - Y坐标
   * @param velocityX - X方向速度
   * @param velocityY - Y方向速度
   * @param life - 生命时长
   * @param color - 颜色
   * @returns 创建的粒子实例
   */
  createParticle(
    x: number, 
    y: number, 
    velocityX: number, 
    velocityY: number, 
    life: number = 1.0, 
    color: string = '#ffffff'
  ): PoolableParticle | null {
    const particle = this.getParticle()
    if (particle) {
      particle.initialize(x, y, velocityX, velocityY, life, color)
    }
    return particle || null
  }

  /**
   * 创建收集品
   * @param x - X坐标
   * @param y - Y坐标
   * @param value - 收集品价值
   * @returns 创建的收集品实例
   */
  createCollectible(x: number, y: number, value: number = 10): PoolableCollectible | null {
    const collectible = this.getCollectible()
    if (collectible) {
      collectible.initialize(x, y, value)
    }
    return collectible || null
  }

  /**
   * 创建投射物
   * @param x - X坐标
   * @param y - Y坐标
   * @param velocityX - X方向速度
   * @param velocityY - Y方向速度
   * @param damage - 伤害值
   * @param range - 射程
   * @returns 创建的投射物实例
   */
  createProjectile(
    x: number, 
    y: number, 
    velocityX: number, 
    velocityY: number, 
    damage: number = 1, 
    range: number = 500
  ): PoolableProjectile | null {
    const projectile = this.getProjectile()
    if (projectile) {
      projectile.initialize(x, y, velocityX, velocityY, damage, range)
    }
    return projectile || null
  }

  /**
   * 预热所有对象池
   * @param particleCount - 粒子预热数量
   * @param collectibleCount - 收集品预热数量
   * @param projectileCount - 投射物预热数量
   */
  warmUpPools(
    particleCount: number = 30, 
    collectibleCount: number = 15, 
    projectileCount: number = 20
  ): void {
    const particlePool = this.poolManager.getPool('particles')
    const collectiblePool = this.poolManager.getPool('collectibles')
    const projectilePool = this.poolManager.getPool('projectiles')

    if (particlePool) particlePool.warmUp(particleCount)
    if (collectiblePool) collectiblePool.warmUp(collectibleCount)
    if (projectilePool) projectilePool.warmUp(projectileCount)
  }

  /**
   * 获取所有池的统计信息
   * @returns 统计信息对象
   */
  getPoolStats(): Record<string, any> {
    return this.poolManager.getAllStats()
  }

  /**
   * 清理所有对象池
   */
  cleanup(): void {
    this.poolManager.clearAll()
  }
}

// 导出全局实例
export const gameObjectPools = GameObjectPools.getInstance()